from flask import g, request
from flask_restful import Resource, marshal, fields
from flask_restful.reqparse import RequestParser

from models.news import Channel, UserChannel, Article
from cache.channel import AllChannelsCache, UserDefaultChannelsCache, UserChannelsCache
from toutiao import db
from toutiao.utils.decorators import loginrequired
from toutiao.utils.parsers import check_channel_id


# 定义类视图
class Index2Resource(Resource):

    def get(self):
        return {
                "index": "index"
        }

# 将频道列表对象转换
channels_fields = {
    'id': fields.Integer,
    'name': fields.String,
}


# 获取所有频道
class ChannelsResource(Resource):
    """获取所有频道"""

    def get(self):

        # # 获取所有可见并且根据序号排序的频道
        # channels = Channel.query.filter(Channel.is_visible == True).order_by(Channel.sequence, Channel.id).all()
        # # 将频道对象转换为字典,并返回,envelope将数据封装
        # return marshal(channels, channels_fields, envelope='channels')

        return AllChannelsCache.get()


# 获取用户关注频道
class UserChannelsResource(Resource):
    """获取用户关注频道"""

    method_decorators = {
        'put': [loginrequired]
    }

    def get(self):

        # 获取用户id
        user_id = g.user_id
        # 判断用户id是否存在
        if user_id:
            # 存在，则查询数据库，用户关注的，没有被删除的，并且按照序号排序
            # channels = UserChannel.query.filter(UserChannel.user_id == user_id,
            #                                     UserChannel.is_deleted == False).order_by(UserChannel.sequence).all()
            channels = UserChannelsCache(user_id).get()
        else:
            # 不存在，则查询默认的, 可见的频道，并按照序号排序
            # channels = Channel.query.filter(Channel.is_default == True,
            #                                 Channel.is_visible == True).order_by(Channel.sequence).all()
            channels = UserDefaultChannelsCache.get()
        # 把查询到的对象转换成字典列表
        channel_dict_list = [
            {
                'id': 0,
                'name': '推荐'
            }
        ] + channels
        # for channel in channels:
        #     channel_dict_list.append({
        #         'id': channel.id,
        #         # 用户关注的频道关联所有频道表 对象.关联字段名.字段名
        #         'name': channel.channel.name if user_id else channel.name
        #     })
        # 返回结果
        return {"channels": channel_dict_list}

    def put(self):
        """修改用户关注频道，只有登陆用户才能修改"""

        # 接收参数
        user_id = g.user_id
        channel_list = request.json.get('channels')
        # 更新数据
        # 先把用户关注的所有频道数据is_delete设置为true
        UserChannel.query.filter(UserChannel.user_id == user_id,
                                 UserChannel.is_deleted == False).update({"is_deleted": True})
        # 然后把前端传过来的频道列表遍历，把每一个频道的is_delete设置为false,并把序号也更新
        for channel in channel_list:
            # 设置序号和is_deleted
            data = {"sequence": channel['seq'], "is_deleted": False}
            # 把每个遍历出来的频道，重新赋值到用户关注频道
            flag = UserChannel.query.filter(UserChannel.user_id == user_id,
                                            UserChannel.channel_id == channel['id']).update(data)

            # 如果没有则新增保存到数据库
            if flag == 0:
                user_channel = UserChannel()
                user_channel.user_id = user_id
                user_channel.sequence = channel.get('seq')
                user_channel.channel_id = channel.get('id')
                db.session.add(user_channel)

            db.session.commit()

        # 在修改关注频道之后，把缓存清理掉，避免在查询时出现修改之前缓存的数据，保证每次查询都是修改之后的数据
        UserChannelsCache(user_id).clear()

        # 返回响应,把请求传过来的频道列表再返回去
        return {"channels": channel_list}, 201


# 查询频道内文章数据
class IndexResource(Resource):
    """查询频道内文章数据"""

    def get(self):

        # 接收参数, 校验参数
        rq = RequestParser()
        rq.add_argument('channel_id', location='args', required=True, type=check_channel_id)
        args = rq.parse_args()
        channel_id = args.get('channel_id')
        # 查询数据库
        articles = Article.query.filter(Article.channel_id == channel_id,
                                        Article.status == Article.STATUS.APPROVED).all()

        # 将对象转换成字典数据
        articles_dict_list = []
        for item in articles:
            articles_dict_list.append({
                "art_id": item.id,
                "title": item.title,
                "aut_id": item.user.id,
                "pubdate": item.ctime.strftime('%Y-%m-%d %H:%M:%S'),
                "aut_name": item.user.name,
                "comm_count": item.comment_count,
                "is_top": False,
                'cover': item.cover,
            })

        # 返回响应
        return {"results": articles_dict_list}